var TetrisGame = {
    rowElemNum:13,
    currBoxMatrix:[],
    currBoxMatrixFirstIdx:4,
    boxstyle:{firstStyle:0,style2:1,style3:2,lastStyle:3},
    boxType:{type1:0,type2:1,type3:2,type4:3,type5:4},
    elemMatrixWidth:3,
    //保存当前方块的样式
    currBoxStyle:0,
    //当前方块的类型
    currBoxType:4,
    //最左(矩阵拆分),左边界,正常，右边界，最右（右拆分）
    boxMatrixPos:{LeftMost:0,LeftBorder:1,Normal:2,RightBorder:3,RightMost:4},
    currBoxMatrixPos:2,
    currBoxLastStyle:1,
    isGamePause:1,
    fixedElemList:[],
    panelDefaultColIdx:5,
    boxColor:["red","CornflowerBlue","green","DarkSalmon","Gold","darkgray"],
    panelELemColorList:[],
    panelELemColorBackUpList:[],
    goal:0,
    AllBoxStyleMatrix:
    [
        // box1
        [
            [0, 1, 0, 0, 1, 1, 0, 1, 0],
            [0, 0, 0, 1, 1, 1, 0, 1, 0],
            [0, 0, 0, 0, 1, 0, 1, 1, 1],
            [0, 1, 0, 1, 1, 0, 0, 1, 0]
        ],
        // box2
        [
            [0,0,1,0,1,1,0,1,0],
            [0,0,0,1,1,0,0,1,1],
            [1,0,0,1,1,0,0,1,0],
            [0,0,0,0,1,1,1,1,0]
        ],
        // box3
        [
            [0,1,0,0,1,0,0,1,1],
            [0,0,0,1,1,1,1,0,0],
            [1,1,0,0,1,0,0,1,0],
            [0,0,0,0,0,1,1,1,1]
        ],
        // box4
        [
            [0,0,0,0,1,1,0,1,1],
        ],
        // box5
        [
            [0,1,0,0,1,0,0,1,0],
            [0,0,0,0,0,0,1,1,1],
        ]
    ],
    initPlayPanel: function() {
        var i = 0;
        for (i = 0; i < 299; i++) {
            $("#main-container").append('<div class = "playPanelElem"></div>');
            this.fixedElemList[i] = 0;
            this.panelELemColorList[i] = this.panelDefaultColIdx;
        }
        TetrisGame.initCurrBox();
    },
    initCurrBox:function(){
        this.currBoxMatrixFirstIdx = 4;
        this.currBoxType = Math.floor(Math.random() * ( this.boxType.type5 + 1));
        //this.currBoxType = this.boxType.type5;
        this.currBoxStyle = 0;
        if ( 3 == this.currBoxType)
            this.currBoxLastStyle = 0;
        else if ( 4 == this.currBoxType)
            this.currBoxLastStyle = 1;
        else
            this.currBoxLastStyle = 3;

        this.currBoxMatrixPos = this.boxMatrixPos.Normal;
    },
    //当前元素矩阵是否是最左
    isCurElemMatrixLeftBorder:function(firstIdx){
        if ( ( (firstIdx) % this.rowElemNum) == 0)
            return true;
        else
            return false;
    },
    isBoxKnocked:function(matrixFirstIdx){
        var ret = false;
        var i = 0;
        var currBoxMatrix = null;
        var currStyleArr = this.AllBoxStyleMatrix[this.currBoxType][this.currBoxStyle];
        
        //方块出底界
        //if ( ( matrixFirstIdx + this.rowElemNum *2) + 2 >= this.fixedElemList.length -1)
        if ( ( matrixFirstIdx + this.rowElemNum *2)  >= this.fixedElemList.length -1)
            return true;
        
        currBoxMatrix =  TetrisGame.calBoxMatrix(matrixFirstIdx);
        for (i = 0; i < currBoxMatrix.length; i++) {
            if (1 == currStyleArr[i]) {
                if (this.fixedElemList[currBoxMatrix[i]] == 1) {
                    ret = true;
                    break;
                }
            }
        }

        return ret;
    },
    isCurElemMatrixRightBorder:function(firstIdx){
        if ( ((firstIdx + 3) % this.rowElemNum) == 0)
            return true;
        else
            return false;
    },
    leftKeyHandle: function() {
        var currBoxMatrixFirstIdx = this.currBoxMatrixFirstIdx;
        var currBoxMatrixPos = this.currBoxMatrixPos;

        if ( this.currBoxMatrixPos == this.boxMatrixPos.LeftMost)
        {
            // nothing to do       
        }
        else if (this.currBoxMatrixPos == this.boxMatrixPos.LeftBorder) 
        {
                if (this.boxstyle.firstStyle == this.currBoxStyle)
                {
                    currBoxMatrixFirstIdx--;
                    currBoxMatrixPos = this.boxMatrixPos.LeftMost;
                }
            
        }
        else if ( this.currBoxMatrixPos == this.boxMatrixPos.Normal)
        {
                currBoxMatrixFirstIdx--;
                if ( TetrisGame.isCurElemMatrixLeftBorder(currBoxMatrixFirstIdx))
                        currBoxMatrixPos = this.boxMatrixPos.LeftBorder;        
        }
        else if ( this.currBoxMatrixPos == this.boxMatrixPos.RightBorder)
        {
                currBoxMatrixFirstIdx--;
                currBoxMatrixPos = this.boxMatrixPos.Normal;
        }
        else if ( this.currBoxMatrixPos == this.boxMatrixPos.RightMost)
        {
                currBoxMatrixFirstIdx--;
                currBoxMatrixPos = this.boxMatrixPos.RightBorder;
        }

        if ( currBoxMatrixFirstIdx != this.currBoxMatrixFirstIdx )
        {
                if ( TetrisGame.isBoxKnocked(currBoxMatrixFirstIdx))
                {
                    TetrisGame.boxKnockedHandle();
                }           
                else
                {
                    this.currBoxMatrixFirstIdx = currBoxMatrixFirstIdx;
                    this.currBoxMatrixPos = currBoxMatrixPos;
                }
        }
    },
    rightKeyHandle: function() {
        var currBoxMatrixFirstIdx = this.currBoxMatrixFirstIdx;
        var currBoxMatrixPos = this.currBoxMatrixPos;

        if (this.currBoxMatrixPos == this.boxMatrixPos.LeftMost) {
            currBoxMatrixFirstIdx++;
            currBoxMatrixPos = this.boxMatrixPos.LeftBorder;
        } else if (this.currBoxMatrixPos == this.boxMatrixPos.LeftBorder) {
            currBoxMatrixFirstIdx++;
            currBoxMatrixPos = this.boxMatrixPos.Normal;
        } else if (this.currBoxMatrixPos == this.boxMatrixPos.Normal) {
            currBoxMatrixFirstIdx++;
            if (TetrisGame.isCurElemMatrixRightBorder(currBoxMatrixFirstIdx))
                currBoxMatrixPos = this.boxMatrixPos.RightBorder;
        } else if (this.currBoxMatrixPos == this.boxMatrixPos.RightBorder) {
            //方块1
            if (this.currBoxType == this.boxType.type1) {
                if (this.currBoxStyle == this.boxstyle.lastStyle) {
                    currBoxMatrixFirstIdx++;
                    currBoxMatrixPos = this.boxMatrixPos.RightMost;
                }
            } else if (this.currBoxType == this.boxType.type2 || this.currBoxStyle == this.boxType.type3) {
                if (this.currBoxStyle == this.boxstyle.style3) {
                    currBoxMatrixFirstIdx++;
                    currBoxMatrixPos = this.boxMatrixPos.RightMost;
                }
            } else if (this.currBoxType == this.boxType.type5) {
                if (this.currBoxStyle == this.boxstyle.firstStyle) {
                    currBoxMatrixFirstIdx++;
                    currBoxMatrixPos = this.boxMatrixPos.RightMost;
                }
            }

        } else if (this.currBoxMatrixPos == this.boxMatrixPos.RightMost) {
            // nothing to do
        }

        if (currBoxMatrixFirstIdx != this.currBoxMatrixFirstIdx) {
            if (TetrisGame.isBoxKnocked(currBoxMatrixFirstIdx)) {
                TetrisGame.boxKnockedHandle();
            } else {
                this.currBoxMatrixFirstIdx = currBoxMatrixFirstIdx;
                this.currBoxMatrixPos = currBoxMatrixPos;
            }
        }
    },
    upKeyHandle: function() {
        if ( this.currBoxMatrixPos != this.boxMatrixPos.LeftMost 
            && this.currBoxMatrixPos != this.boxMatrixPos.RightMost) {
            if (TetrisGame.currBoxStyle < this.currBoxLastStyle)
                TetrisGame.currBoxStyle++;
            else
                TetrisGame.currBoxStyle = TetrisGame.boxstyle.firstStyle;
        }
    },
    boxKnockedHandle:function(matrixFirstIdx){
        var i = 0;
        
        var currStyleArr = this.AllBoxStyleMatrix[this.currBoxType][this.currBoxStyle];

        for ( i = 0; i < this.currBoxMatrix.length ; i++)
        {
            if ( 1 == currStyleArr[i])
            {
                this.fixedElemList[ this.currBoxMatrix[i]] = 1;
            }
        }

        TetrisGame.initCurrBox();
        this.currBoxMatrix = TetrisGame.calBoxMatrix(this.currBoxMatrixFirstIdx);
    },
    downKeyHandle:function(){
        var ret = true;
        var matrixFirstIdx = this.currBoxMatrixFirstIdx;
        matrixFirstIdx += this.rowElemNum;
        if ( TetrisGame.isBoxKnocked(matrixFirstIdx))
        {
            TetrisGame.boxKnockedHandle(matrixFirstIdx);
            ret = false;
            this.goal += 1;
        }
        else
            this.currBoxMatrixFirstIdx = matrixFirstIdx;
        return ret;
    },
    registerkeyPressHandle:function(){
        $(document).keydown( function(e){
            var keyCode = e.keyCode || e.which;
            arrow = {left:37,up:38,right:39,down:40};
            var needUpdate = 0;
            switch(keyCode)
            {
                case arrow.left:
                    TetrisGame.leftKeyHandle();
                    needUpdate = 1;
                    break;
                case arrow.right:
                    TetrisGame.rightKeyHandle();
                    needUpdate = 1;
                    break;
                case arrow.up:
                    TetrisGame.upKeyHandle();
                    needUpdate = 1;
                    break;
                case arrow.down:
                    if (TetrisGame.downKeyHandle())
                    needUpdate = 1;
                    break;

            }
            if ( needUpdate)
                TetrisGame.updatecurrBoxMatrix();
        });

        $("#btn-pause").click(function(){
            TetrisGame.isGamePause = !TetrisGame.isGamePause;
            if (TetrisGame.isGamePause)
                $("#btn-pause").text("start");
            else
                $("#btn-pause").text("pause");
        });
    },
    calBoxMatrix:function(matrixFirstIdx){
        var rowIdx = 0;
        var colIdx = 0;
        var rowBeginAddr =0;
        var arryIdx = 0;  
        var currBoxMatrix = [];      
        //重新计算矩阵的位置
        for (rowIdx = 0, arryIdx = 0; rowIdx < 3; rowIdx++) {
            rowBeginAddr = matrixFirstIdx + this.rowElemNum * rowIdx;
            for (colIdx = 0; colIdx < 3; colIdx++) {
                currBoxMatrix[arryIdx++] = rowBeginAddr + colIdx;
            }
        }
        //左边界特殊处理
        if ( ( matrixFirstIdx + 1 ) % (this.rowElemNum) == 0)
        {
            currBoxMatrix[0] += this.rowElemNum;
            currBoxMatrix[3] += this.rowElemNum;
            currBoxMatrix[6] += this.rowElemNum;
        }
        //右边界特殊处理
        else if ( (matrixFirstIdx + 2) % (this.rowElemNum) == 0)
        {
            currBoxMatrix[2] -= this.rowElemNum ;
            currBoxMatrix[5] -= this.rowElemNum ;
            currBoxMatrix[8] -= this.rowElemNum ;   
        }
        return currBoxMatrix;
    },
    updatecurrBoxMatrix:function(){
        var i = 0;
        
        //将当前矩阵所有的box的颜色恢复默认值
        for (i = 0; i < this.currBoxMatrix.length; i++) {
            arryIdx = this.currBoxMatrix[i];
            
            //当前矩阵的边缘与已固定方块不重合
            if ( this.fixedElemList[arryIdx] != 1)
               this.panelELemColorList[arryIdx] = this.panelDefaultColIdx;
        }
        
        //获取移动后的当前矩阵
        this.currBoxMatrix = TetrisGame.calBoxMatrix(this.currBoxMatrixFirstIdx);

        var currStyle = this.AllBoxStyleMatrix[this.currBoxType][this.currBoxStyle];
        TetrisGame.setNewMatrix(this.currBoxMatrix,currStyle);
        TetrisGame.drawbox();
    },

    //currBoxMatrix：当前方块矩阵
    //currStyleArr:当前矩阵的形状
    setNewMatrix:function(currBoxMatrix,currStyleArr){
        var i = 0;
        var arryIdx = 0;
        
        for ( i = 0 ; i < currBoxMatrix.length ; i++)
        {
            if ( currStyleArr[i] == 1)
            {
                 //panelELem[currBoxMatrix[i]].style.backgroundColor = this.boxColor[this.currBoxType];
                 this.panelELemColorList[currBoxMatrix[i]] = this.currBoxType;    
            }   
        }
    },

    drawbox:function(){
        var i = 0;
        var AllPanelElem = $("#main-container").children();
        for ( i = 0 ; i < this.panelELemColorList.length ; i++)
        {
            if ( this.panelELemColorList[i] != this.panelELemColorBackUpList[i])
            {
                this.panelELemColorBackUpList[i] = this.panelELemColorList[i];
                AllPanelElem[i].style.backgroundColor = this.boxColor[this.panelELemColorBackUpList[i]];
            }
        }
    },
    disTestData: function() {
        var i = 0;
        var j = 0;
        var arryIdx = 0;
        var AllPanelElem = $("#main-container").children();
        var Matrix = [];

        var beginAddr1 =  2;
        var beginAddr2 =  6;
        var beginAddr3 =  54;
        var beginAddr4 =  58;
        var baseBeginAddr = 0;
        var currBoxStyle = 0;
        var currStyle;
        var currBoxType = this.boxType.type3;

        var times = 0;
        for (times = 0 ; times < 4; times++) {
            if ( 0 == times)
                baseBeginAddr = 2;
            else if ( 1 == times)
                baseBeginAddr = 6;
            else if ( 2 == times)
                baseBeginAddr = 54;
            else
                baseBeginAddr = 58;
            for (i = baseBeginAddr ,arryIdx = 0; i < baseBeginAddr + this.rowElemNum * 3; i += this.rowElemNum) {
                for (j = i; j < i + 3; j++) {
                    Matrix[arryIdx++] = j;
                }
            }

            currBoxStyle = times;
            currStyle = this.AllBoxStyleMatrix[currBoxType][currBoxStyle];
            TetrisGame.setNewMatrix(Matrix, currStyle);
        }
    },
    startGame: function() {

        TetrisGame.initPlayPanel();
        TetrisGame.registerkeyPressHandle();
        TetrisGame.updatecurrBoxMatrix();
        setInterval(function() {
            if ( 0 == TetrisGame.isGamePause )
            {
                if (TetrisGame.downKeyHandle())
                {
                    //panelELem,panelELemColor,rowSize,panelELemSize
                    EliminateBox.eliminate(TetrisGame.fixedElemList,TetrisGame.panelELemColorList,TetrisGame.rowElemNum,TetrisGame.panelELemColorList.length);
                    TetrisGame.updatecurrBoxMatrix();
                    $("#dis_goal").html(TetrisGame.goal);
                }

            }    
        }, 400);
        //TetrisGame.disTestData();
    }
}

var EliminateBox = {
    
    //当前行是否满(堆满方块)
    isCurrRowFull:function(panelELem,rowBeginAddr,rowSize){
        var i = 0;
        for ( i = 0 ; i < rowSize ; i++ )
        {
            if ( panelELem[ rowBeginAddr + i] == 0 )
                break;
        }

        if ( i >= rowSize)
        {
            console.log("row:"+rowBeginAddr+"full.");
             return 1;
        }   
        else
            return 0;
    },

    // 清空当前行
    clearCurrFullRow:function(panelELem,panelELemColor,rowBeginAddr,rowSize){
        var i = 0;
        for ( i = 0 ; i < rowSize ; i++ )
        {
            panelELem[ rowBeginAddr + i] = 0;
            panelELemColor[ rowBeginAddr + i] = TetrisGame.panelDefaultColIdx;
        }
    },

    //行复制
    rowCopy:function(panelELem,panelELemColor,srcBeginIdx,destBeginIdx,rowSize){
        var i =  0;
        for ( i = 0 ; i < rowSize ; i++)
        {
            panelELem[ destBeginIdx + i ] = panelELem[ srcBeginIdx + i]; 
            panelELemColor[ destBeginIdx + i]  = panelELemColor[srcBeginIdx+i];           
        }
    },

    //找到最高层的方块的行起始地址
    getHightestRowBeginAddr:function(panelELem,rowSize,panelELemSize){
        var idx = 0;
        var firstOccupiedElemIdx = 0;
        var beginAddr = 0;

        //
        for ( idx = 0; idx < panelELemSize ; idx++)
        {
            if ( panelELem[idx] == 1 )
            {
                firstOccupiedElemIdx = idx;
                break;
            }
        }
        if ( idx >= panelELemSize)
            beginAddr = panelELemSize+1;
        else
            beginAddr = (firstOccupiedElemIdx / rowSize) * rowSize;
        return beginAddr;

    },

    //boxCnt
    //
    eliminate:function(panelELem,panelELemColor,rowSize,panelELemSize){
        var rowBeginAddr = panelELemSize - rowSize;
        var i = 0;
        var highestRowBeginAddr = EliminateBox.getHightestRowBeginAddr(panelELem,rowSize,panelELemSize);
        //console.log("rowBeginAddr:"+rowBeginAddr);
        //console.log("highestRowBeginAddr:"+highestRowBeginAddr);
        if (highestRowBeginAddr < panelELemSize) {
            while (rowBeginAddr >= highestRowBeginAddr) {
                if (EliminateBox.isCurrRowFull(panelELem, rowBeginAddr, rowSize)) {
                    EliminateBox.clearCurrFullRow(panelELem, panelELemColor, rowBeginAddr, rowSize);
                    i = 0;
                    while ( rowBeginAddr - i * rowSize >= highestRowBeginAddr)
                    {
                        EliminateBox.rowCopy(panelELem, panelELemColor, rowBeginAddr - (i+1) * rowSize, rowBeginAddr - i*rowSize, rowSize);
                        EliminateBox.clearCurrFullRow(panelELem, panelELemColor, rowBeginAddr - (i+1) * rowSize, rowSize);
                        i++;
                    }
                    TetrisGame.goal += 10;
                }

                if (rowBeginAddr > rowSize)
                    rowBeginAddr -= rowSize;
                else
                    break;
            }
        }
    }
}

$(document).ready(TetrisGame.startGame);
